using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System;
using UnityEngine;
using UnityEngine.Timeline;

namespace IQIGame.Onigao.GamePlay
{
    [ExecuteAlways]
    public class EntityDriver : MonoBehaviour, IMaterialChangeable
    {
        /// <summary>
        /// 实体动作播放时需要用到的VFX通用Timeline
        /// </summary>
        public static TimelineAsset commonTimeline;

        /// <summary>
        /// 所有绑定的Object，一般是特效和需要控制隐藏的节点
        /// 不要乱用，是给控制显隐逻辑用的
        /// </summary>
        public GameObject[] objectBinding;

        /// <summary>
        /// 所有的render
        /// 不要乱用，是工具自动收集所有的Render
        /// </summary>
        public Renderer[] renderers;

        /// <summary>
        /// 当前实体是否包含动作视效
        /// </summary>
        public bool isAnimatorVFXExisted;

        /// <summary>
        /// 修改材质的属性
        /// </summary>
        public MaterialPropertyBlock matProperties { private set; get; }

        public string debugName => this.name;

        private Action<EntityDriver> _onDestroy;

        /// <summary>
        /// 默认音频包
        /// </summary>
        public string defaultAudioSheet { get; set; }

        public void Awake()
        {
            if (renderers != null && renderers.Length > 0)
            {
                matProperties = new MaterialPropertyBlock();
                var firstRenderer = renderers[0];
                if (firstRenderer != null)
                {
                    firstRenderer.GetPropertyBlock(matProperties);
                }
                else
                {
                    Debug.LogError($"实体（资源：{gameObject?.name}）renderers生成有问题。");
                }
            }
            // 尝试修改一次默认色阶
            EntityDriverEnvironment.Instance.defaultMatColorValueAction?.Invoke(this);

            if (isAnimatorVFXExisted && commonTimeline != null)
            {
                var behaviourFeatureComp = GetComponent<BehaviorFeatureComp>();
                behaviourFeatureComp?.AddTimelineAsset(commonTimeline);
            }
        }


        //void Update()
        //{
        //    if (renderers != null && renderers.Length > 0)
        //    {
        //        // 刷新平面阴影高度
        //        for (var i = 0; i < renderers.Length; i++)
        //        {
        //            var render = renderers[i];
        //            var y = render.transform.position.y;
        //            if (matProperties != null)
        //            {
        //                matProperties.SetFloat(GameRender.ShaderKeywords.WorldSpacePosY, y);
        //                render.SetPropertyBlock(matProperties);
        //            }
        //        }
        //    }
        //}


        void OnDestroy()
        {
            _onDestroy?.Invoke(this);
        }

        #region material && region

        private BetterPrioritizeList<MaterialChangeRegion> _regionList;

        /// <summary>
        /// 材质球SetFloat
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public void MatSetFloat(string name, float value)
        {
            if (renderers != null && renderers.Length > 0)
            {
                matProperties.SetFloat(name, value);
                for (var i = 0; i < renderers.Length; i++)
                {
                    var render = renderers[i];
                    render.SetPropertyBlock(matProperties);
                }
            }
        }

        public void MatSetFloat(int name, float value)
        {
            if (renderers.Length > 0)
            {
                matProperties.SetFloat(name, value);
                for (var i = 0; i < renderers.Length; i++)
                {
                    var render = renderers[i];
                    render.SetPropertyBlock(matProperties);
                }
            }
        }


        public bool AddMatChangeRegion(MaterialChangeRegion region)
        {
            if (renderers == null || renderers.Length == 0)
            {
                return false;
            }
            if (_regionList == null)
            {
                _regionList = new BetterPrioritizeList<MaterialChangeRegion>();
            }
            // 按照priority优先级从小到大拆入
            int insertIndex = _regionList.AddByPriority(region);
            if (insertIndex == _regionList.Count - 1)
            {
                // 如果是最后一个，那么需要生效
                if (_regionList.Count > 0 && _regionList[_regionList.Count - 1].ChangeMaterialValue(this))
                {

                }
            }
            return true;
        }

        public bool RemoveMatChangeRegion(MaterialChangeRegion region)
        {
            if (_regionList == null)
            {
                return false;
            }
            var removeIndex = _regionList.RemoveGetIndex(region);
            if (removeIndex >= 0)
            {
                if (removeIndex == _regionList.Count)
                {
                    // 如果是最后一个，就是当前生效的那个
                    // 如果当前还有生效的区域，就用生效最后一个区域的色阶值
                    if (_regionList.Count > 0 && _regionList[_regionList.Count - 1].ChangeMaterialValue(this))
                    {

                    }
                    else
                    {
                        // 如果没有，那么就还原为默认的值
                        EntityDriverEnvironment.Instance.defaultMatColorValueAction?.Invoke(this);
                    }
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// 刷新材质区域，如果是当前生效的区域，就刷新。
        /// 当前生效的是_regionList的最后一个，_regionList的有序列表
        /// </summary>
        /// <param name="region"></param>
        public void RefreshMatRegion(MaterialChangeRegion region)
        {
            if (_regionList == null || _regionList.Count == 0)
            {
                return;
            }
            if (_regionList[_regionList.Count - 1] == region)
            {
                // 当前是生效，需要刷新
                region.ChangeMaterialValue(this);
            }
        }


        public void RegisterDestroyEvent(Action<IMaterialChangeable> action)
        {
            _onDestroy += action;
        }

        public void UnRegisterDestroyEvent(Action<IMaterialChangeable> action)
        {
            _onDestroy -= action;
        }

        #endregion

        #region 动画事件相关

        /// <summary>
        /// 通过索引获取绑定的Object
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public GameObject GetObjectByIndex(int index)
        {
            if (index < 0 || index >= objectBinding.Length)
            {
                Debug.LogError($"[{gameObject?.name}]动画事件触发显隐GameObject错误。index out of range. index: {index}, entity obj length: {objectBinding.Length}");
                return null;
            }
            return objectBinding[index];
        }

        /// <summary>
        /// 实体资源配置Id，用于之后的播放音效
        /// </summary>
        // public int entityResId;
        public void ActiveObject(int index)
        {
            GetObjectByIndex(index)?.SetActive(true);
        }

        public void DeactiveObject(int index)
        {
            GetObjectByIndex(index)?.SetActive(false);
        }


        public void PlayAudio(int audioId)
        {
            ManagerCenter.Audio.PlayAudioById(audioId);
        }

        public void PlayFootStep()
        {
            if (string.IsNullOrEmpty(defaultAudioSheet))
            {
                //没有音频包
                return;
            }

            int groundId = 0;
            if (_groundTriggers != null && _groundTriggers.TryGetPrioritizeItem(out var item))
            {
                groundId = item.groundId;
            }
            else
            {
                groundId = EntityDriverEnvironment.Instance.defaultGroundId;
            }

            if (groundId <= 0)
            {
                return;
            }

            var groundCfg = TableCenter.sceneGround.Get(groundId);
            if (groundCfg == null)
            {
                return;
            }

            // 播放音效
            ManagerCenter.Audio.PlayAudio(groundCfg.FootSteps, defaultAudioSheet, AudioSourceType.SfxSource);
        }
        #endregion

        #region 物理触发相关

        private BetterPrioritizeList<SceneGroundTrigger> _groundTriggers;

        private void AddSceneGroudTrigger(SceneGroundTrigger groundTrigger)
        {
            if (_groundTriggers == null)
            {
                _groundTriggers = new BetterPrioritizeList<SceneGroundTrigger>();
            }
            var addedIndex = _groundTriggers.AddByPriority(groundTrigger);
            if (addedIndex == _groundTriggers.Count - 1)
            {
                // 是最优先那个
                OnSceneGroudChanged();
            }
        }


        private bool RemoveSceneGroudTrigger(SceneGroundTrigger groundTrigger)
        {
            if (_groundTriggers == null || _groundTriggers.Count == 0)
            {
                return false;
            }
            var removeIndex = _groundTriggers.RemoveGetIndex(groundTrigger);
            if (removeIndex >= 0)
            {
                if (removeIndex == _groundTriggers.Count)
                {
                    OnSceneGroudChanged();
                    // 如果是最后一个，就是当前生效的那个
                    // 如果当前还有生效的区域，就用生效最后一个区域的色阶值
                    //if (_groundTriggers.Count > 0 && _groundTriggers[_groundTriggers.Count - 1].ChangeMaterialValue(this))
                    //{

                    //}
                    //else
                    //{
                    //    // 如果没有，那么就还原为默认的值
                    //    defaultMatColorValueAction?.Invoke(this);
                    //}
                }
                return true;
            }
            return false;
        }

        private void OnSceneGroudChanged()
        {

        }


        private void OnTriggerEnter(Collider other)
        {
            var triggerMono = other.GetComponent<ISceenTriggerMono>();
            if (triggerMono == null)
            {
                return;
            }
            switch (triggerMono)
            {
                case SceneGroundTrigger sceneGroundTrigger:
                    AddSceneGroudTrigger(sceneGroundTrigger);
                    break;
            }
        }

        private void OnTriggerExit(Collider other)
        {
            var triggerMono = other.GetComponent<ISceenTriggerMono>();
            if (triggerMono == null)
            {
                return;
            }
            switch (triggerMono)
            {
                case SceneGroundTrigger sceneGroundTrigger:
                    RemoveSceneGroudTrigger(sceneGroundTrigger);
                    break;
            }
        }

        #endregion
    }
}
